"""
Contains convenience utility methods to be used by tests that need to handle storage domains
"""
from pprint import pformat

import uuid
from enum import Enum

eDomainClass = Enum(
    data = 1,
    ISO = 2,
    )

def destroyDomainTargets(client, domainTargets):
    """
    Takes care of destroying all the resources allocated for a domain target.

    :param client: the VDSClient to use.
    :param domainTargets: a list of domain targets.
    """
    domainTargets = domainTargets[:] #So we won't change the users list
    for domainTarget in domainTargets[:]:
        if ":" in domainTarget: #VGs don't contain ':' but all nfs mounts do.
            domainTargets.remove(domainTarget)

    # Because getVGList is a slow action we make sure that we actually
    # have targets that are not nfs before calling it.
    if len(domainTargets) == 0:
        return

    vgList = client.getVGList()['vglist']
    for vg in vgList:
        if vg['vgUUID'] in domainTargets:
            resp = client.removeVG(vg['vgUUID'])
            if resp['status']['code'] != 0:
                raise Exception("Failed to remove VG '%s' due to (%d: %s)" %
                    (vg['vgUUID'], resp['status']['code'], resp['status']['message']))

def generateDomainTargets(client, connections, domainDeclarations):
    """
    Returns the deduced domain targets from the domain declarations.

    :param client: the VDSClient to use.
    :param connections: a collection of lists ``( (connection name, storage type, connection dict), ...)``.
    :param domainDeclarations: A collection of lists.
                               In each sublist can be a NFS connection name or a list of device GUIDs.
                               EX. ``( [(nfs connection name) | (Device GUID, ....)], ....)``.

    :returns: a list of strings that contain for each of the declarations the resolved domain target.
              The results are in the order of the declarations.
    """
    domainTargets = []
    for domainDcl in domainDeclarations:
        found = False
        for name, type, connection in connections:
            if len(domainDcl) == 1 and name == domainDcl[0]:
                found = True
                domainTargets.append(connection["connection"])
                break

        if not found:
            domainTargets.append(_createVG(client, domainDcl))

    return tuple(domainTargets)

def _createVG(client, vgDeviceGuids):
    """
    Safly create VGs from the devices.
    Makes sure that the devices exist and are not part of any VG.

    :param client: the VDSClient to use.
    :param vgDeviceGuids: a list of GUIDs ``(device guid, ...)`` from which to create the VG.

    :returns: the UUID of the new VG.
    """
    #Make sure devices are valid and free
    availableDevices = client.getDeviceList()['devList']
    #print pformat(availableDevices)
    devicesToFind = list(vgDeviceGuids)
    for device in availableDevices:
        if device['GUID'] in vgDeviceGuids:
            if device['vgUUID'] != "":
                raise ValueError("Device '%s' is already in a VG." % device['GUID'])
            devicesToFind.remove(device['GUID'])

    if len(devicesToFind) > 0:
        raise ValueError("Could not find device/s '%s'." % ", ".join(devicesToFind))

    #Create VG
    resp = client.createVG(uuid.generate(), vgDeviceGuids)
    if resp['status']['code'] != 0:
        raise Exception("Could not create VG (%s)" % resp)
    return resp['uuid']

